package com.smec.moblie.location;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.google.gson.Gson;
import com.smec.moblie.bean.Gps;
import com.smec.moblie.bean.LocationNameBean;
import com.smec.moblie.util.NetworkUtil;
import com.smec.moblie.util.PositionUtil;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cz.msebera.android.httpclient.client.ClientProtocolException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/***
 * 发送坐标service
 *
 * @author xinwei.sun
 */
public class SmecMntMapService extends Service {

    public static final String ACTION = "com.smec.remes.mobile.centre.test.SmecMntMapService";
    //	public static final String path = "http://10.1.11.117:8888/SmecMntMapService/mnt_post_location_service";//测试环境
    public static final String path = "http://bpmpublic.smec-cn.com:8011/SmecMntMapService/mnt_post_location_service";//正式环境
    /**
     * 线程池
     */
    private ExecutorService mExecutorService = Executors.newCachedThreadPool();
    /**
     * 电源控制
     */
    private WakeLock wakeLock = null;
    /**
     * 经纬度
     */
    private String locationInfo = "";
    private int i = 0;
    /**
     * 日志
     */
    private static StringBuffer log = new StringBuffer();
    /**
     * 为上传坐标
     */
    private static StringBuffer logLocation = new StringBuffer();
    /**
     * 网络情况
     */
    private String netState = "";
    /**
     * 获取经纬度service
     */
    private LocationService locationService;
    /**
     * 文件处理工具类
     */
    private Fileservice fileservice;
    /**
     * 保存一分钟之前的坐标
     */
    private SharedPreferences preferences;

    public LocationClient mLocationClient = null;
    /**
     * 设备id
     */
    String deviceId;

    public class mThreadSmecMntMap implements Runnable {
        String result = "";
        String log = "";

        @Override
        public void run() {
            boolean isNet = NetworkUtil.checkNet(getApplicationContext());
            try {

                String locationInfos[] = {};
                // 获取SharedPreferences中保存的账号密码，没有返回""
                SharedPreferences mySharedPreferences = getSharedPreferences(
                        "ElevatorSharedPreferences", MODE_PRIVATE);
                String username = mySharedPreferences.getString("USERNAME", "UNKOWN");

                if (!"".equals(locationInfo)) {
                    locationInfos = locationInfo.split(",");
                    if (isNet && i % 1 == 0) {// 10分钟上传一次坐标
                        result = getResultForHttpGet(locationInfos[0],
                                locationInfos[1], username, "m",
                                System.currentTimeMillis() + "", deviceId);// 发送坐标
                        Log.i("log", "~~location update back" + result);
                    } else if ("".equals(result) && i % 1 == 0) {// 若上传失败保存坐标
                        // 上传失败时 有获取道坐标保存坐标没获取到坐标就取一分钟之前的。
                        String lo = "";
                        String la = "";
                        SharedPreferences preferences = getApplicationContext()
                                .getSharedPreferences("SmecMntMapService",
                                        Context.MODE_PRIVATE);
                        lo = preferences.getString("lon", "");
                        la = preferences.getString("lat", "");
                        if (!"".equals(locationInfo)) {
                            saveLocation(locationInfos[0], locationInfos[1],
                                    username, "m", System.currentTimeMillis()
                                            + "");// 记录该坐标有网络的时候再发送
                        } else {
                            saveLocation(lo, la, username, "m",
                                    System.currentTimeMillis() + "");// 记录该坐标有网络的时候再发送
                        }
                        saveLocation(locationInfos[0], locationInfos[1],
                                username, "m", System.currentTimeMillis() + "");// 记录该坐标有网络的时候再发送
                    }
                    Editor editor = preferences.edit();
                    editor.putString("lon", locationInfos[0]);
                    editor.putString("lat", locationInfos[1]);

                    Gps gps = PositionUtil.gcj02_To_Bd09(Double.parseDouble(locationInfos[1]), Double.parseDouble(locationInfos[0]));
                    editor.commit();
                    Log.i("log", "~~~lon = " + locationInfos[0] + ",lat = " + locationInfos[1] + ",gps.lon = " + gps.getWgLon() + ",gps.la = " + gps.getWgLat());
                    //逆地理查询
                    try {
                        String ret = getLocationName("http://api.map.baidu.com/geocoder?output=json&location=" + gps.getWgLat() + "," + gps.getWgLon() + "&key=37492c0ee6f924cb5e934fa08c6b1676");
                        Gson gson = new Gson();
                        LocationNameBean locationNameBean = gson.fromJson(ret, LocationNameBean.class);
                        LocationNameBean.ResultEntity ret1 = locationNameBean.getResult();
                        ret = ret1.getFormatted_address();
                        Editor editor1 = preferences.edit();
                        editor1.putString("LocationName", ret);
                        editor1.commit();
                    } catch (Exception e) {
                        Log.i("test", "~~~逆地理查询错误：" + e);
                    }
                    log = i + "," + getTime() + "\nlon:" + locationInfos[0]
                            + "，lat:" + locationInfos[1] + "\nresult：" + result;
                    save(log);
                }
                i++;
                locationInfo = "";
                locationService.stop();
                if (!fileservice.readSDFile("smecLocationlog.txt").isEmpty()) {
                    if (isNet) {// 上传未上传坐标
                        int locationNumber = ServiceUtil
                                .getCachelocation(getApplicationContext());
                        for (int i = 0; i < locationNumber; i++) {
                            String value = ServiceUtil.getCachelocation(
                                    getApplicationContext(), i);
                            String result = getResultForHttpGet(value);
                            if (i + 1 == locationNumber && !"".equals(result)) {
                                fileservice.saveContentTosdCard(
                                        "smecLocationlog.txt", "");// 清空smecLocationlog.txt
                                logLocation.setLength(0);// 清空StringBuffer
                                save(i + "，\n上传失败坐标重新上传结果" + result);
                            }
                        }

                    }
                }

            } catch (Exception e) {
                if ("".equals(result) || "".equals(log)) {
                    save("第" + i + "次" + getTime() + netState + "\n"
                            + locationInfo + "\n" + e.toString());
                } else if ("".equals(locationInfo)) {
                    locationService.start(isNet, getApplicationContext());
                }
            }
        }
    }

    /**
     * get接口获取数据
     *
     * @param url
     * @return
     * @throws IOException
     */
    private String getLocationName(String url) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();

        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    /**
     * 发送坐标
     *
     * @param lon    经度
     * @param lat    纬度
     * @param user   当前用户
     * @param type   f表示急修 m表示维保
     * @param device 设备id
     * @return 上传结果
     * @throws IOException
     */
    public String getResultForHttpGet(String lon, String lat, String user,
                                      String type, String date, String device) throws Exception {
        return "{\"code\":\"0\",\"msg\":\"\"}";
//        String uri = path + "?lon=" + lon + "&lat=" + lat + "&user=" + user
//                + "&type=" + type + "&date=" + date + "&device=" + device;
//        Log.i("log", "~~Location uri = " + uri);
//        String result = "";
//        URL url = new URL(uri);
//        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//        conn.setConnectTimeout(60000);
//        conn.setRequestMethod("GET");
//        conn.connect();
//        DataInputStream dis = new DataInputStream(conn.getInputStream());
//        result = dis.readLine();
//        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
//            return "";
//        }
//        return result;
    }

    /***
     * @param value 参数拼接
     * @return 请求结果
     * @throws
     * @throws IOException
     */
    public String getResultForHttpGet(String value)
            throws ClientProtocolException, IOException {
        String uri = path + value;
        String result = "";
        URL url = new URL(uri);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(60000);
        conn.setRequestMethod("GET");
        conn.connect();
        DataInputStream dis = new DataInputStream(conn.getInputStream());
        result = dis.readLine();
        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return "";
        }
        return result;
    }

    /***
     * 日志保存
     */
    private void save(String str) {
        log.append(str + "\n");
        fileservice.saveContentTosdCard("smecElevatorApplog.txt",
                log.toString());
    }

    /***
     * 坐标保存
     */
    private void saveLocation(String lon, String lat, String user, String type,
                              String date) {
        String value = "," + lon + "&" + lat + "&" + user + "&" + type + "&"
                + date + "&" + deviceId;
        logLocation.append(value);
        fileservice.saveContentTosdCard("smecLocationlog.txt",
                logLocation.toString());
    }

    /***
     * 获取当前系统时间
     */
    public static String getTime() {
        SimpleDateFormat sDateFormat = new SimpleDateFormat(
                "yyyy-MM-dd hh:mm:ss");
        String date = sDateFormat.format(new java.util.Date());
        return date;
    }

    /**
     * 收听网络状态
     */
    class NetState extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent arg1) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo gprs = manager
                    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            NetworkInfo wifi = manager
                    .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (!gprs.isConnected() && !wifi.isConnected()) {
                netState = "connectfail";
            } else {
                netState = "connectsuccess";
            }
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        acquireWakeLock();

        NetState receiver = new NetState();// 注册广播获取网络状态
        IntentFilter filterintent = new IntentFilter();
        filterintent.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        this.registerReceiver(receiver, filterintent);
        receiver.onReceive(this, null);

        locationService = new LocationService(getApplicationContext());
        locationService.registerListener(mListener);
        locationService.setLocationOption(locationService
                .getDefaultLocationClientOption());

        fileservice = new Fileservice(SmecMntMapService.this);

        preferences = getSharedPreferences("SmecMntMapService",
                Context.MODE_WORLD_READABLE);

        TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        deviceId = TelephonyMgr.getDeviceId();

        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(mListener);
        initLocation();
    }

    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy
        );//可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
//        option.setCoorType("bd09ll");//可选，默认gcj02，设置返回的定位结果坐标系
        int span = 1000;
        option.setScanSpan(span);//可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true);//可选，默认false,设置是否使用gps
        option.setLocationNotify(true);//可选，默认false，设置是否当GPS有效时按照1S/1次频率输出GPS结果
        option.setIgnoreKillProcess(false);//可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false);//可选，默认false，设置是否收集CRASH信息，默认收集
        mLocationClient.setLocOption(option);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    /**
     * 请求字符串
     *
     * @param str
     */
    public void logMsg(String str) {
        try {
            locationInfo = str;
            String locationInfos[] = {};
            locationInfos = locationInfo.split(",");
            if (!isNum(locationInfos[0]) || !isNum(locationInfos[1])) {
                locationInfo = "0,0";
            }
        } catch (Exception e) {
            locationInfo = "0,0";
        }

    }

    public static boolean isNum(String str) {
        return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
    }

    /**
     * 解析返回结果
     *
     * @param jsonstr
     */
    private msg getJsonmsg(String jsonstr) {

        Gson gson = new Gson();
        msg m;
        m = gson.fromJson(jsonstr, msg.class);
        return m;
    }

    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        if (!ServiceUtil.isOPen(getApplicationContext())) {
            ServiceUtil.openGPS(getApplicationContext());
        }
        locationService.start(NetworkUtil.checkNet(getApplicationContext()),
                getApplicationContext());
        mExecutorService.execute(new mThreadSmecMntMap());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, START_REDELIVER_INTENT,
                Service.START_REDELIVER_INTENT);
    }

    /*****
     * 通过百度sdk获取经纬度
     */
    private BDLocationListener mListener = new BDLocationListener() {

        @Override
        public void onReceiveLocation(BDLocation location) {

            if (null != location
                    && location.getLocType() != BDLocation.TypeServerError) {
                StringBuffer sb = new StringBuffer(256);
                sb.append(location.getLongitude());
                sb.append(",");
                sb.append(location.getLatitude());
                sb.append(",");
                sb.append("\n" + LocationService.codeMsg(location.getLocType()));
                sb.append(",");
                /**
                 * 时间也可以使用systemClock.elapsedRealtime()方法 获取的是自从开机以来，每次回调的时间；
                 * location.getTime() 是指服务端出本次结果的时间，如果位置不发生变化，则时间不变
                 */
                sb.append(location.getTime());
                if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果
                    sb.append("\nspeed : ");
                    sb.append(location.getSpeed());// 单位：km/h
                    sb.append("\nsatellite : ");
                    sb.append(location.getSatelliteNumber());
                    sb.append("\nheight : ");
                    sb.append(location.getAltitude());// 单位：米
                    sb.append("\ndescribe : ");
                    sb.append("gps定位成功");
                } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果
                    // 运营商信息
                    sb.append("\noperationers : ");
                    sb.append(location.getOperators());
                    sb.append("\ndescribe : ");
                    sb.append("网络定位成功");
                } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果
                    sb.append("\ndescribe : ");
                    sb.append("离线定位成功，离线定位结果也是有效的");
                } else if (location.getLocType() == BDLocation.TypeServerError) {
                    sb.append("\ndescribe : ");
                    sb.append("服务端网络定位失败，可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com，会有人追查原因");
                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                    sb.append("\ndescribe : ");
                    sb.append("网络不同导致定位失败，请检查网络是否通畅");
                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                    sb.append("\ndescribe : ");
                    sb.append("无法获取有效定位依据导致定位失败，一般是由于手机的原因，处于飞行模式下一般会造成这种结果，可以试着重启手机");
                }
                logMsg(sb.toString());
            }
        }

    };

    /**
     * 获取电源锁，保持该服务在屏幕熄灭时仍然获取CPU时，保持运行
     */
    private void acquireWakeLock() {
        if (null == wakeLock) {
            PowerManager pm = (PowerManager) this
                    .getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
                    | PowerManager.ON_AFTER_RELEASE, "SmecMntM" + ""
                    + "apService");
            if (null != wakeLock) {
                wakeLock.acquire();
            }
        }
    }

    /**
     * 释放设备电源锁
     */
    private void releaseWakeLock() {
        if (null != wakeLock) {
            wakeLock.release();
            wakeLock = null;
        }
    }

    /***
     * 解析上传坐标结果
     *
     * @author xinwei.sun
     */
    public class msg implements Serializable {
        private static final long serialVersionUID = 1L;
        private String code = "";
        private String msg = "";

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

    }

}
